home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume2 / intuitin / snipit12.1 < prev    next >
Text File  |  1988-12-11  |  53KB  |  2,268 lines

  1. Path: xanth!nic.MR.NET!tank!ncar!mailrus!ulowell!page
  2. From: page@swan.ulowell.edu (Bob Page)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v02i095:  snipit - cut/paste text from/to window with mouse v1.2
  5. Message-ID: <10646@swan.ulowell.edu>
  6. Date: 11 Dec 88 05:47:15 GMT
  7. Organization: University of Lowell, Computer Science Dept.
  8. Lines: 2257
  9. Approved: page@swan.ulowell.edu
  10.  
  11. Submitted-by: scott@applix.uucp (Scott Evernden)
  12. Posting-number: Volume 2, Issue 95
  13. Archive-name: intuition/snipit12.1
  14.  
  15.                    - SnipIt 1.2 - 
  16.  
  17.     SnipIt is an input handler wedge which allows
  18.     you to clip text from any window, and then paste
  19.     that text anywhere, as though you had typed it
  20.     on the keyboard.
  21.  
  22.     New in SnipIt 1.2 are the following:
  23.  
  24.     o Now attempts to work in all windows and consoles.
  25.       P-Edit and VT100 now can be snipped from.
  26.  
  27.     o Automatically detaches itself and runs in the
  28.       background- no Run/RunBack required.
  29.  
  30.     o Built-in mini help (type: snipit h).
  31.  
  32.     o Keyboard option to insert a short string at the
  33.       beginning of each pasted line.
  34.  
  35.     o Options to move/adjust/correct snip/recognizer cell
  36.       area independently for consoles and windows.
  37.  
  38.     o Can recognize highlighted text.
  39.  
  40.     o Option to freeze window layer while snipping.
  41.  
  42. #    This is a shell archive.
  43. #    Remove everything above and including the cut line.
  44. #    Then run the rest of the file through sh.
  45. #----cut here-----cut here-----cut here-----cut here----#
  46. #!/bin/sh
  47. # shar:    Shell Archiver
  48. #    Run the following text with /bin/sh to create:
  49. #    readme
  50. #    makefile
  51. #    hs.h
  52. #    detach.c
  53. #    hand.c
  54. #    main.c
  55. #    patch.c
  56. #    reco.c
  57. #    snipit.keys
  58. #    patch.doc
  59. #    snipit.doc
  60. # This archive created: Sun Dec 11 00:43:21 1988
  61. cat << \SHAR_EOF > readme
  62.  
  63.                    - SnipIt 1.2 - 
  64.  
  65.     SnipIt is an input handler wedge which allows
  66.     you to clip text from any window, and then paste
  67.     that text anywhere, as though you had typed it
  68.     on the keyboard.
  69.  
  70.     New in SnipIt 1.2 are the following:
  71.  
  72.     o Now attempts to work in all windows and consoles.
  73.       P-Edit and VT100 now can be snipped from.
  74.  
  75.     o Automatically detaches itself and runs in the
  76.       background- no Run/RunBack required.
  77.  
  78.     o Built-in mini help (type: snipit h).
  79.  
  80.     o Keyboard option to insert a short string at the
  81.       beginning of each pasted line.
  82.  
  83.     o Options to move/adjust/correct snip/recognizer cell
  84.       area independently for consoles and windows.
  85.  
  86.     o Can recognize highlighted text.
  87.  
  88.     o Option to freeze window layer while snipping.
  89.  
  90.  
  91.       - Scott Evernden
  92.  
  93. SHAR_EOF
  94. cat << \SHAR_EOF > makefile
  95. CFLAG = 
  96. LFLAGS = -w
  97. CFLAGS = $(CFLAG) +ihs.i
  98. OBJS = main.o hand.o reco.o
  99.  
  100. snipit: $(OBJS) detach.o
  101.     ln $(LFLAGS) -o $* $(OBJS) detach.o -lc
  102.     beep
  103.  
  104. detach.o: detach.c
  105.  
  106. $(OBJS): hs.i
  107.  
  108. hs.i: hs.h
  109.     cc -o nil: +hhs.i hs.h
  110.  
  111. final:
  112.     @make LFLAGS=
  113.  
  114. SHAR_EOF
  115. cat << \SHAR_EOF > hs.h
  116. #include <exec/types.h>
  117. #include <exec/ports.h>
  118. #include <exec/memory.h>
  119. #include <exec/devices.h>
  120. #include <exec/execbase.h>
  121. #include <exec/interrupts.h>
  122. #include <graphics/gfxbase.h>
  123. #include <intuition/intuition.h>
  124. #include <intuition/intuitionbase.h>
  125. #include <libraries/dos.h>
  126. #include <libraries/dosextens.h>
  127. #include <devices/conunit.h>
  128. #include <devices/keymap.h>
  129. #include <devices/input.h>
  130. #include <devices/inputevent.h>
  131.  
  132. struct ConsoleBase {
  133.     struct Device conDevice;
  134.     char reserved[26];
  135.     struct List conUnits;
  136. };
  137.  
  138. #include <functions.h>
  139.  
  140. /* mouse states */
  141. #define M_UP    0
  142. #define M_MOVE    1
  143. #define M_DOWN    2
  144.  
  145. /* 'snip' container defines */
  146. #define CON_SNIP    1
  147. #define WIN_SNIP    2
  148.  
  149. #define PRE_SIZE    32
  150.  
  151.  
  152. SHAR_EOF
  153. cat << \SHAR_EOF > detach.c
  154. /* Copyright (C) 1986,1987 by Manx Software Systems, Inc. */
  155.  
  156. /* Hacked up for SnipIt 1.2 use - Scott Evernden */
  157.  
  158. #include <exec/memory.h>
  159. #include <libraries/dosextens.h>
  160. #include <functions.h>
  161.  
  162. struct Process *_FindTask();
  163. void *_AllocMem();
  164. long _Open();
  165.  
  166. #define STACK_SIZE    3000L
  167.  
  168. extern BPTR output;
  169. extern long running;
  170.  
  171. extern char *_procname;
  172. extern char *_detach_name;
  173. static long _alen = 0;
  174. static char *_aptr = 0;
  175.  
  176. #asm
  177.     dseg
  178.     public    __savsp
  179.     cseg
  180. #endasm
  181.  
  182. do_detach(alen, aptr)
  183. long *alen;
  184. char **aptr;
  185. {
  186.     register struct CommandLineInterface *cli;
  187.     register struct Process *pp;
  188.     register unsigned short c;
  189.     register char *cp;
  190.     register long l;
  191.     long *lp, *sav;
  192.     struct MemList *mm;
  193.  
  194.     pp = _FindTask(0L);
  195.  
  196.     /* first time through!! */
  197.     if (pp->pr_CLI) {
  198.  
  199.         cli = (struct CommandLineInterface *) ((long)pp->pr_CLI << 2);
  200.         l = cli->cli_Module;
  201.  
  202.         output = (BPTR) _Open("*", MODE_OLDFILE);
  203.  
  204.         _alen = *alen;
  205.         _aptr = _AllocMem(_alen, 0L);
  206.         movmem(*aptr, _aptr, (int)_alen);
  207.  
  208.         cp = (char *)((long)cli->cli_CommandName << 2);
  209.         _detach_name = AllocMem((long)cp[0]+1, 0L);
  210.         movmem(cp, _detach_name, cp[0]+1);
  211. #asm
  212.         move.l    __savsp,-(sp)
  213. #endasm
  214.         cli->cli_Module = 0;
  215.         CreateProc(_procname, 0L, l, STACK_SIZE);
  216.         while (running == 0)
  217.             Delay(5L);
  218. #asm
  219.         move.l    (sp)+,sp
  220.         move.l    #0,d0
  221.         rts
  222. #endasm
  223.     }
  224.  
  225.     /* second time through */
  226.     else if (strcmp(pp->pr_Task.tc_Node.ln_Name, _procname) == 0) {
  227.  
  228.         lp = (long *)((long)pp->pr_SegList << 2);
  229.         lp = (long *)(lp[3] << 2);
  230.         sav = lp;
  231.         c = 2;
  232.         while (lp) {
  233.             lp = (long *)(*lp << 2);
  234.             c++;
  235.         }
  236.         mm = _AllocMem((long)sizeof(struct MemList)+
  237.                             (c-1)*sizeof(struct MemEntry), 0L);
  238.         lp = sav;
  239.         mm->ml_NumEntries = c;
  240.         c = 0;
  241.         while (lp) {
  242.             mm->ml_me[c].me_Addr = (APTR)lp - 1;
  243.             mm->ml_me[c].me_Length = lp[-1];
  244.             lp = (long *)(*lp << 2);
  245.             c++;
  246.         }
  247.         mm->ml_me[c].me_Addr = (APTR)_aptr;
  248.         mm->ml_me[c++].me_Length = _alen;
  249.         mm->ml_me[c].me_Addr = (APTR)_detach_name;
  250.         mm->ml_me[c++].me_Length = _detach_name[0] + 1;
  251.  
  252.         AddTail(&((struct Task *)pp)->tc_MemEntry, mm);
  253.  
  254.         *alen = _alen;
  255.         *aptr = _aptr;
  256.     }
  257. }
  258.  
  259. SHAR_EOF
  260. cat << \SHAR_EOF > hand.c
  261. /* :ts=4
  262.  *
  263.  * Amiga SnipIt 1.2
  264.  * (c) (opyright 1987,1988 - Scott Evernden - All Rights Reserved
  265.  * 
  266.  * hand.c - input event handler & snipper & lib function replacements
  267.  *
  268.  */
  269.  
  270. #include "hs.h"
  271.  
  272. int state;                    /* mouse state */
  273. int snip;                    /* container type which is highlighted */
  274. int maxx, maxy;                /* maximum cells in snipped layer */
  275. int origx, origy;            /* pixel origin in conunit */
  276. int charx, chary;            /* pixel size of char cell of conunit */
  277. int lastx, lasty;            /* last cell highlighted */
  278. int con_offx, con_offy;        /* correction offsets for console windows */
  279. int win_offx, win_offy;        /* correction offsets for non-console windows */
  280. int snipx[2], snipy[2];        /* snip area; top/left to bottom/right */
  281. int left, right;            /* sides of snip area, irrespective of rows */
  282.  
  283. struct TextFont *capttf;    /* non-NULL indicates recognition required */
  284. struct Window *snipw;        /* clipped text window */
  285. struct RastPort *sniprp;    /* rastport of clipped text window */
  286.  
  287. struct RastPort captrp;        /* rastport holding clipped snip area */
  288. struct BitMap captbm;        /* bitmap into which snipped area is copied */
  289. int captx, capty;            /* dimensions of capture map */
  290. int jobFlag;                /* flag input handler to ignore mouse events */
  291. int lock_layer;                /* lock window/console layer while snipping */
  292. int windows=1;                /* include windows in layer search */
  293.  
  294. int cmd1 = IEQUALIFIER_LCOMMAND;
  295. int cmd2 = IEQUALIFIER_LALT;
  296.  
  297. extern struct IntuitionBase *IntuitionBase;
  298. extern struct ConsoleBase *ConsoleBase;
  299. extern struct Task *myTask;
  300. extern int mySignal;
  301.  
  302. /* this does one at a time */
  303. struct InputEvent *doEvent();
  304.  
  305. /*********************************************/
  306. #asm
  307.  
  308.     public    _geta4
  309.  
  310. ; Trap these Gfx/Intui functions; purpose is to remove hilighting, if nec.
  311. ; Not all possible cases are handled (window resizing, for example), but
  312. ; the most common ones are.
  313.  
  314.     public    _myRectFill
  315.     public    _myScrollRaster
  316.     public    _myCloseWindow
  317.  
  318.     public    _oldRectFill
  319.     public    _oldScrollRaster
  320.     public    _oldCloseWindow
  321.  
  322. _myRectFill:            ; pardon me
  323.     move.l    a4,-(sp)
  324.     jsr        _geta4                ; establish addressing
  325.     tst.w    _snip
  326.     beq.s    1$                    ; no highlighted area; get out
  327.     cmpa.l    _sniprp,a1
  328.     bne.s    1$                    ; not the same RastPort; get out
  329.     movem.l    a1/d0-d5,-(sp)
  330.     jsr        _clearHi            ; de-highlight
  331.     movem.l    (sp)+,a1/d0-d5
  332. 1$:    movea.l    _oldRectFill,a0
  333.     movea.l    (sp)+,a4
  334.     jmp        (a0)                ; continue into library
  335.  
  336. _myScrollRaster:        ; 'scuse
  337.     move.l    a4,-(sp)
  338.     jsr        _geta4
  339.     tst.w    _snip
  340.     beq.s    1$
  341.     cmpa.l    _sniprp,a1
  342.     bne.s    1$
  343.     movem.l    a1/d0-d5,-(sp)
  344.     jsr        _clearHi
  345.     movem.l    (sp)+,a1/d0-d5
  346. 1$:    movea.l    _oldScrollRaster,a0
  347.     movea.l    (sp)+,a4
  348.     jmp        (a0)
  349.  
  350. _myCloseWindow:
  351.     move.l    a4,-(sp)
  352.     jsr        _geta4
  353.     tst.w    _snip
  354.     beq.s    1$
  355.     cmpa.l    _snipw,a0
  356.     bne.s    1$                    ; not the same Window; get out
  357.     clr.w    _snip
  358.     clr.l    _capttf                ; Window closing; reset indicators
  359. 1$:    movea.l    _oldCloseWindow,a1
  360.     movea.l    (sp)+,a4
  361.     jmp        (a1)
  362.  
  363. ;************************
  364.  
  365. ; input event stream glue
  366.     public    _handlerCode
  367.  
  368. _handlerCode:
  369.     movem.l    d2/d3/a0/a1/a4/a6,-(sp)    ; i think this is right
  370.     jsr        _geta4
  371.     jsr        _myHandler
  372.     movem.l    (sp)+,d2/d3/a0/a1/a4/a6
  373.     rts
  374.  
  375. #endasm
  376. /*********************************************/
  377.  
  378. /* SnipIt's input event handler */
  379. struct InputEvent *myHandler(d2, d3, ev)
  380. long d2, d3;
  381. register struct InputEvent *ev;
  382. {
  383.     register struct InputEvent *inev, **evp;
  384.     struct InputEvent *outev;
  385.  
  386.     if (jobFlag)
  387.         return ev;
  388.  
  389.     inev = ev;
  390.     outev = NULL;
  391.  
  392.     /* back-pointer */
  393.     evp = &outev;
  394.  
  395.     /*
  396.      * Loop thru the possibly linked list of events.
  397.      * We remove the ones having meaning to SnipIt, and leave the others
  398.      */
  399.     while (inev) {
  400.         ev = inev;
  401.         inev = ev->ie_NextEvent;
  402.  
  403.         /* ensure that main code isn't running and this is a mouse event */
  404.         if (ev->ie_Class == IECLASS_RAWMOUSE)
  405.             ev = doEvent(ev);
  406.  
  407.         /* patch back-pointer */
  408.         if (*evp = ev)
  409.             evp = &ev->ie_NextEvent;
  410.     }
  411.  
  412.     /* pass 'em along */
  413.     return outev;
  414. }
  415.  
  416. /*********************************************/
  417.  
  418. /* handle a single (mouse) input event */
  419. struct InputEvent *doEvent(ev)
  420. register struct InputEvent *ev;
  421. {
  422.     static int lflag, rflag, cmd;
  423.     register UWORD code;
  424.     register int x, y;
  425.  
  426.     x = ev->ie_X;
  427.     y = ev->ie_Y;
  428.     code = ev->ie_Code;
  429.  
  430.     /* in mid-snip? */
  431.     if (lflag && code == IECODE_NOBUTTON &&
  432.                             (ev->ie_Qualifier & IEQUALIFIER_LEFTBUTTON)) {
  433.  
  434.         mouse(M_MOVE, x, y);
  435.         return ev;
  436.     }
  437.  
  438.     /* button transition event... */
  439.     code &= ~IECODE_UP_PREFIX;
  440.  
  441.     /* mouse button down event? */
  442.     if ((ev->ie_Code & IECODE_UP_PREFIX) == 0)  {
  443.  
  444.         if (cmd = ev->ie_Qualifier & (cmd1 | cmd2)) {
  445.  
  446.             if (!rflag && code == IECODE_LBUTTON) {
  447.                 lflag++;
  448.                 mouse(M_DOWN, x, y);
  449.             }
  450.  
  451.             else if (!lflag && code == IECODE_RBUTTON)
  452.                 rflag++;        /* note transition */
  453.  
  454.             return NULL;
  455.         }
  456.     }
  457.  
  458.     /* release of left mouse button? */
  459.     else if (lflag && code == IECODE_LBUTTON) {
  460.         lflag = 0;
  461.         mouse(M_UP, x, y);
  462.         return NULL;
  463.     }
  464.  
  465.     /* release of right mouse button? */
  466.     else if (rflag && code == IECODE_RBUTTON) {
  467.         rflag = 0;
  468.  
  469.         /* kick main code */
  470.         jobFlag = cmd;
  471.         Signal(myTask, 1L << mySignal);    
  472.         return NULL;
  473.     }
  474.  
  475.     /* event back into stream */
  476.     return ev;
  477. }
  478.  
  479. /*********************************************/
  480.  
  481. /* find a console containing the layer holding (x,y); return success flag */
  482. int whichConsole(layer, x, y)
  483. struct Layer *layer;
  484. int x, y;
  485. {
  486.     register struct ConUnit *cu, *rcu;
  487.     register struct Node *node;
  488.  
  489.     /* result conunit */
  490.     rcu = NULL;
  491.  
  492.     _Forbid();
  493.  
  494.     /* begin at the beginning */
  495.     node = ConsoleBase->conUnits.lh_Head;
  496.  
  497.     /* next is NULL when back at listhead */
  498.     while (node->ln_Succ) {
  499.         cu = (struct ConUnit *) node;
  500.  
  501.         /* see if console window's layer is the same */
  502.         if (cu && cu->cu_Window && cu->cu_Window->RPort->Layer == layer) {
  503.             rcu = cu;    /* found it */
  504.             break;
  505.         }
  506.  
  507.         node = node->ln_Succ;
  508.     }
  509.  
  510.     Permit();
  511.  
  512.     if (rcu) {
  513.         snip = CON_SNIP;
  514.         snipw = rcu->cu_Window;
  515.         sniprp = snipw->RPort;
  516.         charx = rcu->cu_XRSize;
  517.         chary = rcu->cu_YRSize;
  518.         origx = rcu->cu_XROrigin;
  519.         origy = rcu->cu_YROrigin;
  520.         maxx = rcu->cu_XMax;
  521.         maxy = rcu->cu_YMax;
  522.     }
  523.  
  524.     return rcu != NULL;
  525. }
  526.  
  527. /*********************************************/
  528.  
  529. /* find a window containing the layer holding (x,y); return success flag */
  530. int whichWindow(s, layer, x, y)
  531. struct Screen *s;
  532. struct Layer *layer;
  533. int x, y;
  534. {
  535.     register struct Window *w, *rw;
  536.  
  537.     if (!windows)
  538.         return NULL;
  539.  
  540.     /* result window */
  541.     rw = NULL;
  542.  
  543.     _Forbid();
  544.  
  545.     w = s->FirstWindow;
  546.     while (w) {
  547.         if (w->WLayer == layer) {
  548.             rw = w;
  549.             break;
  550.         }
  551.  
  552.         w = w->NextWindow;
  553.     }
  554.  
  555.     Permit();
  556.  
  557.     if (rw) {
  558.         snip = WIN_SNIP;
  559.         snipw = rw;
  560.         sniprp = snipw->RPort;
  561.         charx = sniprp->Font->tf_XSize;
  562.         chary = sniprp->Font->tf_YSize;
  563.         origx = rw->BorderLeft;
  564.         origy = rw->BorderTop;
  565.         maxx = (rw->Width - rw->BorderRight - origx) / charx - 1;
  566.         maxy = (rw->Height - rw->BorderBottom - origy) / chary - 1;
  567.     }
  568.  
  569.     return rw != NULL;
  570. }
  571.  
  572. /*********************************************/
  573.  
  574. /* handle meaningful mouse activity */
  575. mouse(event, mx, my)
  576. int event;
  577. register int mx, my;
  578. {
  579.     static struct Screen *s;
  580.     static struct Layer *layer;
  581.  
  582.     if (event == M_DOWN)
  583.         s = IntuitionBase->FirstScreen;
  584.  
  585.     /* correct raw positions according to this screen */
  586.     if (!(s->ViewPort.Modes & LACE))
  587.         my /= 2;
  588.  
  589.     mx += s->MouseX - 2;        /* accumulate deltas */
  590.     my += s->MouseY - 1;        /* x,y adjusted for feel */
  591.  
  592.     if (event == M_DOWN) {
  593.  
  594.         /* de-hilight, if nec. */
  595.         if (snip)
  596.             hiSnip(0);
  597.  
  598.         /* turn flag off */
  599.         snip = 0;
  600.  
  601.         /* locate pointed-at layer */
  602.         if ((layer = WhichLayer(&s->LayerInfo, (long) mx, (long) my)) &&
  603.             (whichConsole(layer, mx, my) || whichWindow(s, layer, mx, my))) {
  604.  
  605.             /* if mouse down in title line area, remain clear */
  606.             if (my - snipw->TopEdge < origy)
  607.                 snip = 0;
  608.         }
  609.     }
  610.  
  611.     /* nothing interesting */
  612.     if (!snip)
  613.         return;
  614.  
  615.     /* mouse to window-relative cell coordinates */
  616.     mx = (mx - snipw->LeftEdge - origx) / charx;
  617.     if (mx < 0)
  618.         mx = 0;
  619.     else if (maxx < mx)
  620.         mx = maxx;
  621.  
  622.     my = (my - snipw->TopEdge  - origy) / chary;
  623.     if (my < 0)
  624.         my = 0;
  625.     else if (maxy < my)
  626.         my = maxy;
  627.  
  628.     /* highlighting games ahead */
  629.  
  630.     if (event == M_DOWN) {
  631.         state = M_DOWN;
  632.         if (lock_layer)
  633.             LockLayerRom(layer);
  634.  
  635.         snipx[0] = mx;
  636.         snipy[0] = my;
  637.         hiLite(mx, my, 1, 1);
  638.     }
  639.  
  640.     else if (event == M_UP) {
  641.         snipx[1] = mx;
  642.         snipy[1] = my;
  643.         if (state == M_MOVE)
  644.             hiLite(lastx, lasty, 1, 1);
  645.         hiLite(snipx[0], snipy[0], 1, 1);
  646.         hiSnip(charx == 8);
  647.  
  648.         state = M_UP;
  649.         if (charx != 8)        /* only able to do 8 pixel wide fonts */
  650.             clearHi();
  651.  
  652.         if (lock_layer)
  653.             UnlockLayerRom(layer);
  654.     }
  655.  
  656.     else if (mx != lastx || my != lasty) {
  657.         if (state == M_MOVE)
  658.             hiLite(lastx, lasty, 1, 1);
  659.         hiLite(lastx = mx, lasty = my, 1, 1);
  660.         state = M_MOVE;
  661.     }
  662. }
  663.  
  664. /*********************************************/
  665.  
  666. /* de-highlight; snip is known to be set */
  667. clearHi()
  668. {
  669.     if (state == M_UP)
  670.         hiSnip(0);
  671.  
  672.     else if (lock_layer)
  673.         return;
  674.  
  675.     else {
  676.         hiLite(snipx[0], snipy[0], 1, 1);
  677.         if (state == M_MOVE)
  678.             hiLite(lastx, lasty, 1, 1);
  679.     }
  680.  
  681.     snip = 0;
  682. }
  683.  
  684. /*********************************************/
  685.  
  686. /* local cleanup for this module */
  687. finiHand()
  688. {
  689.     int i;
  690.     PLANEPTR p;
  691.  
  692.     if (snip)
  693.         clearHi();
  694.  
  695.     if (p = captbm.Planes[0])
  696.         FreeRaster(p, (long) captx, (long) capty);
  697. }
  698.  
  699. /*********************************************/
  700.  
  701. /* manufacture rastport with bitmap, ready to receive captured bitmap */
  702. int allocMap(sx, sy)
  703. int sx, sy;
  704. {
  705.     PLANEPTR p;
  706.  
  707.     /* release previous, if any */
  708.     if (p = captbm.Planes[0]) {
  709.         FreeRaster(p, (long) captx, (long) capty);
  710.         captbm.Planes[0] = NULL;
  711.     }
  712.  
  713.     /* record new map size */
  714.     captx = sx;
  715.     capty = sy;
  716.  
  717.     /* build new bitmap to contain snipped area */
  718.     InitBitMap(&captbm, 1L, (long) captx, (long) capty);
  719.     InitRastPort(&captrp);
  720.     captrp.BitMap = &captbm;
  721.  
  722.     /* allocate bitmap planes */
  723.     p = (PLANEPTR) AllocRaster((long) captx, (long) capty);
  724.     if (!p)
  725.         return 0;
  726.  
  727.     captbm.Planes[0] = p;
  728.     return 1;
  729. }
  730.  
  731. /*********************************************/
  732.  
  733. /* video reverse the capture area; perform capture if flagged */
  734. hiSnip(capt)
  735. int capt;
  736. {
  737.     register int px, py, qx, qy, tx, ty;
  738.     long ox, oy;
  739.  
  740.     /* need these vars to be handy */
  741.     tx = maxx;
  742.  
  743.     /* take care of backward snip areas */
  744.     if (snipy[0] < snipy[1] ||
  745.         snipy[0] == snipy[1] && snipx[0] <= snipx[1]) {
  746.  
  747.         px = snipx[0];
  748.         py = snipy[0];
  749.         qx = snipx[1];
  750.         qy = snipy[1];
  751.     }
  752.     else {
  753.         px = snipx[1];
  754.         py = snipy[1];
  755.         qx = snipx[0];
  756.         qy = snipy[0];
  757.     }
  758.  
  759.     /* only if capturing more than 1 cell... */
  760.     if (capt && (px != qx || py != qy)) {
  761.  
  762.         /* left and right sides */
  763.         left = px;
  764.         right = qx;
  765.  
  766.         /* get a new bitmap */
  767.         if (allocMap((tx + 1) * charx, (qy - py + 1) * chary)) {
  768.  
  769.             /* copy console contents into snip-map */
  770.             ox = origx;
  771.             oy = origy + py * chary;
  772.  
  773.             if (snip == CON_SNIP) {        /* user-specified corrections */
  774.                 ox += con_offx;
  775.                 oy += con_offy;
  776.             }
  777.             else {
  778.                 ox += win_offx;
  779.                 oy += win_offy;
  780.             }
  781.  
  782.             ClipBlit(sniprp, ox, oy, &captrp, 0L, 0L,
  783.                             (long) captx, (long) capty, 0xC0L);
  784.  
  785.             /* note new info in snip-map */
  786.             capttf = sniprp->Font;
  787.         }
  788.  
  789.         else {
  790.             /* no memory, act dumb */
  791.             snip = captx = capty = 0;
  792.             return;
  793.         }
  794.     }
  795.  
  796.     /* perform hilighting */
  797.     while (py <= qy) {
  798.  
  799.         if (py == qy)
  800.             tx = qx;
  801.  
  802.         hiLite(px, py, tx - px + 1, 1);
  803.  
  804.         px = 0;
  805.         py++;
  806.     }
  807. }
  808.  
  809. /*********************************************/
  810.  
  811. /* low-lever video reverser */
  812. hiLite(x, y, xs, ys)
  813. int x, y, xs, ys;
  814. {
  815.     register long ox, oy;
  816.  
  817.     ox = origx + x * charx;
  818.     oy = origy + y * chary;
  819.  
  820.     if (snip == CON_SNIP) {        /* user-specified corrections */
  821.         ox += con_offx;
  822.         oy += con_offy;
  823.     }
  824.     else {
  825.         ox += win_offx;
  826.         oy += win_offy;
  827.     }
  828.  
  829.     ClipBlit(sniprp, ox, oy,  sniprp, ox, oy,
  830.                         (long) (xs * charx), (long) (ys * chary), 0x50L);
  831. }
  832.  
  833. /*********************************************/
  834. SHAR_EOF
  835. cat << \SHAR_EOF > main.c
  836. /* :ts=4
  837.  *
  838.  * Amiga SnipIt 1.2
  839.  * (c) (opyright 1987,1988 - Scott Evernden - All Rights Reserved
  840.  *
  841.  * main.c - cutter/paster like SunTools
  842.  *
  843.  * Permission is granted to modify and redistribute as long
  844.  * as this notice is left intact.
  845.  *
  846.  */
  847.  
  848. /**********************
  849.  
  850.     The strategy here begins with the installation of some input handler
  851.     code into the input event handler chain.  This code looks for mouse
  852.     actions and keyboard presses that indicate that text is being snipped,
  853.     or is being pasted.
  854.  
  855.     Snipped text (plane 0) is always immediately copied into a temp 1-plane
  856.     bitmap without further processing.  Subsequents "snips" cause the old
  857.     snipped bitmap to be thrown away, and a new one captured.
  858.  
  859.     Pasting requires that the text in the capture bitmap be recognized.
  860.     This is not done in the input handler code, since it would cause all
  861.     pending input events to pile up while the recognizer is running.
  862.     Instead, the input handler code signals the main snipit code (RUNning
  863.     in the background, itself) to do the recognition and fake the kb events.
  864.     During this period, the input handler code temporarily suspends its
  865.     special processing waiting for the main code (recognizer) to finish.
  866.  
  867.     Once a capture bitmap has been recognized and converted into a sequence
  868.     of key codes, it is deallocated, and subsequent pastes don't require
  869.     the recognition step.
  870.  
  871. **********************/
  872.  
  873. #include "hs.h"
  874.  
  875. struct Task *_FindTask();
  876. struct Library *_OpenLibrary();
  877.  
  878. BPTR output = 0;
  879.  
  880. long LayersBase;                    /* for WhichLayer() */
  881. struct GfxBase *GfxBase;
  882. struct IntuitionBase *IntuitionBase;
  883. struct ConsoleBase *ConsoleBase;    /* defined in hs.h */
  884.  
  885. /* communication with input.device */
  886. struct IOStdReq *inpReq;
  887. struct MsgPort *inpPort;
  888.  
  889. /* communication with console.device */
  890. struct MsgPort *conPort;
  891. struct IOStdReq *conReq;
  892.  
  893. /* who I am */
  894. struct Task *myTask;
  895.  
  896. /* snipit's port */
  897. struct MsgPort *myPort;
  898.  
  899. struct MyMessage {
  900.     struct Message m;
  901.     int done, huh, off;
  902.     int w_offx, w_offy;
  903.     int c_offx, c_offy;
  904.     long alen;
  905.     char *aptr;
  906. } myMsg, *msgp;
  907.  
  908. /* for snipit's input handler */
  909. struct Interrupt handler;
  910.  
  911. /* flags handler installation for cleanup */
  912. int handlerIn;
  913.  
  914. /* snipit's allocated signal bit */
  915. int mySignal = -1L;
  916.  
  917. /* snipit's input handler code */
  918. VOID handlerCode();
  919.  
  920. /* snipit replacement functions */
  921. VOID myRectFill(), myScrollRaster(), myCloseWindow();
  922.  
  923. /* remember original library vectors */
  924. long oldRectFill, oldScrollRaster, oldCloseWindow;
  925.  
  926. /* vector offsets of certain functions */
  927. extern int lvoRectFill, lvoScrollRaster, lvoCloseWindow;
  928.  
  929. /* detach stuff */
  930. long running = 0;
  931. char *_procname = "\x9B33mSnipIt 1.2\x9B0m";
  932.  
  933. char *huh_msg =   "Huh?  (for help type: snipit h)";
  934.  
  935. /* "Can't open"... forms */
  936. char *i_libname = "~intuition.library";
  937. char *g_libname = "~graphics.library";
  938. char *l_libname = "~layers.library";
  939. char *i_devname = "~input.device";
  940. char *c_devname = "~console.device";
  941.  
  942. char *port_name = "^\x9B33mSnipIt 1.2\x9B0m Port";
  943.  
  944. long _savsp;
  945.  
  946. extern int jobFlag;
  947. extern int con_offx, con_offy;
  948. extern int win_offx, win_offy;
  949. extern int cmd1, cmd2;
  950. extern int snip, lock_layer, windows;
  951. extern char preString[];
  952.  
  953. /*********************************************/
  954. /* pick up the ABS symbols describing gfx/intui lib offsets
  955.  */
  956. #asm
  957.     dseg
  958.     public    _LVORectFill
  959.     public    _LVOScrollRaster
  960.     public    _LVOCloseWindow
  961.  
  962. _lvoRectFill        dc.w    _LVORectFill
  963. _lvoScrollRaster    dc.w    _LVOScrollRaster
  964. _lvoCloseWindow        dc.w    _LVOCloseWindow
  965.  
  966.     cseg
  967. #endasm
  968.  
  969. /*********************************************/
  970.  
  971. writes(str)
  972. register char *str;
  973. {
  974.     register char *piece;
  975.     register long len;
  976.  
  977.     len = 0;
  978.  
  979.     if (*str == '!') {
  980.         piece = "Can't ";
  981.         len = 6;
  982.     }
  983.     else if (*str == '~') {
  984.         piece = "Can't open ";
  985.         len = 11;
  986.     }
  987.     else if (*str == '^') {
  988.         piece = "Can't create ";
  989.         len = 13;
  990.     }
  991.     else if (*str == '_') {
  992.         piece = _procname;
  993.         len = 17;
  994.     }
  995.  
  996.     if (len) {
  997.         str++;
  998.         _Write(output, piece, len);
  999.     }
  1000.  
  1001.     /* output a message & newline */
  1002.     _Write(output, str, (long) strlen(str));
  1003.     _Write(output, "\n", 1L);
  1004. }
  1005.  
  1006. /*********************************************/
  1007.  
  1008. fini()
  1009. {
  1010.     long stat;
  1011.  
  1012.     /* cleanup in other modules */
  1013.     finiHand();
  1014.     finiReco();
  1015.  
  1016.     /* restore gfx/intui library vectors */
  1017.     if (oldRectFill)
  1018.         SetFunction(GfxBase, (long) lvoRectFill, oldRectFill);
  1019.  
  1020.     if (oldScrollRaster)
  1021.         SetFunction(GfxBase, (long) lvoScrollRaster, oldScrollRaster);
  1022.  
  1023.     if (oldCloseWindow)
  1024.         SetFunction(IntuitionBase, (long) lvoCloseWindow, oldCloseWindow);
  1025.  
  1026.     /* remove snipit input handler */
  1027.     if (handlerIn) {
  1028.         inpReq->io_Command = IND_REMHANDLER;
  1029.         inpReq->io_Data = (APTR) &handler;
  1030.         DoIO(inpReq);
  1031.     }
  1032.  
  1033.     /* close down console.device */
  1034.     if (conReq) {
  1035.         if (conReq->io_Device)
  1036.             CloseDevice(conReq);
  1037.         DeleteStdIO(conReq);
  1038.     }
  1039.     if (conPort)
  1040.         DeletePort(conPort);
  1041.  
  1042.     /* close down input.device */
  1043.     if (inpReq) {
  1044.         if (inpReq->io_Device)
  1045.             CloseDevice(inpReq);
  1046.         DeleteStdIO(inpReq);
  1047.     }
  1048.     if (inpPort)
  1049.         DeletePort(inpPort);
  1050.  
  1051.     /* release snipit's port & signal bit */
  1052.     if (myPort)
  1053.         DeletePort(myPort);
  1054.  
  1055.     if (mySignal != -1)
  1056.         FreeSignal(1L << mySignal);
  1057.  
  1058.     /* close libraries */
  1059.     if (GfxBase)
  1060.         _CloseLibrary(GfxBase);
  1061.  
  1062.     if (LayersBase)
  1063.         _CloseLibrary(LayersBase);
  1064.  
  1065.     if (IntuitionBase)
  1066.         _CloseLibrary(IntuitionBase);
  1067.  
  1068.     if (output)
  1069.         _Close(output);
  1070.  
  1071. #asm
  1072.     moveq    #0,d0            ;pick up return exit code
  1073.     move.l    __savsp,sp        ;get back original stack pointer
  1074.     rts                        ;and exit
  1075. #endasm
  1076. }
  1077.  
  1078. /*********************************************/
  1079.  
  1080. int init()
  1081. {
  1082.     long stat;
  1083.  
  1084.     /* global record of this task's ID */
  1085.     myTask = _FindTask((char *) NULL);
  1086.  
  1087.     /* need intuitionbase to read mouse pos. & screen layer */
  1088.     IntuitionBase = (struct IntuitionBase *) _OpenLibrary(i_libname + 1, 0L);
  1089.     if (IntuitionBase == NULL) {
  1090.         writes(i_libname);
  1091.         return 0;
  1092.     }
  1093.  
  1094.     /* need graphics since we do */
  1095.     GfxBase = (struct GfxBase *) _OpenLibrary(g_libname + 1, 0L);
  1096.     if (GfxBase == NULL) {
  1097.         writes(g_libname);
  1098.         return 0;
  1099.     }
  1100.  
  1101.     /* layers for WhichLayer() */
  1102.     LayersBase = (long) _OpenLibrary(l_libname + 1, 0L);
  1103.     if (LayersBase == NULL) {
  1104.         writes(l_libname);
  1105.         return 0;
  1106.     }
  1107.  
  1108.     /* signal from input event handler to main code */
  1109.     mySignal = AllocSignal(-1L);
  1110.     if (mySignal == -1) {
  1111.         writes("!allocate a signal bit.");
  1112.         return 0;
  1113.     }
  1114.  
  1115.     /* a signal to this port will terminate us */
  1116.     myPort = CreatePort(port_name + 1, 0L);
  1117.     if (myPort == NULL) {
  1118.         writes(port_name);
  1119.         return 0;
  1120.     }
  1121.  
  1122.     /* port to the input.device */
  1123.     inpPort = CreatePort((char *) NULL, 0L);
  1124.     if (inpPort == NULL) {
  1125.         writes("^input.device port.");
  1126.         return 0;
  1127.     }
  1128.  
  1129.     /* need an i/o request */
  1130.     inpReq = CreateStdIO(inpPort);
  1131.     if (inpReq == NULL) {
  1132.         writes("^input.device i/o request.");
  1133.         return 0;
  1134.     }
  1135.  
  1136.     /* open input.device */
  1137.     stat = OpenDevice(i_devname + 1, 0L, inpReq, 0L);
  1138.     if (stat != 0) {
  1139.         writes(i_devname);
  1140.         return 0;
  1141.     }
  1142.  
  1143.     /* port to the console.device */
  1144.     conPort = CreatePort((char *) NULL, 0L);
  1145.     if (!conPort) {
  1146.         writes("^console.device port.");
  1147.         return 0;
  1148.     }
  1149.  
  1150.     /* need an i/o request */
  1151.     conReq = CreateStdIO(conPort);
  1152.     if (!conReq) {
  1153.         writes("^console.device i/o request.");
  1154.         return 0;
  1155.     }
  1156.  
  1157.     /* open console.device */
  1158.     stat = OpenDevice(c_devname + 1, -1L, conReq, 0L);
  1159.     if (stat != 0) {
  1160.         writes(c_devname);
  1161.         return 0;
  1162.     }
  1163.  
  1164.     /* check for consolebase */
  1165.     ConsoleBase = (struct ConsoleBase *) conReq->io_Device;
  1166.     if (!ConsoleBase) {
  1167.         writes("!find ConsoleBase.");
  1168.         return 0;
  1169.     }
  1170.  
  1171.     /* handler command stuff */
  1172.     handler.is_Code = handlerCode;
  1173.     handler.is_Node.ln_Pri = 51;
  1174.  
  1175.     /* install new input event handler */
  1176.     inpReq->io_Command = IND_ADDHANDLER;
  1177.     inpReq->io_Data = (APTR) &handler;
  1178.  
  1179.     stat = DoIO(inpReq);
  1180.     if (stat != 0) {
  1181.         writes("ADDHANDLER request failed.");
  1182.         return 0;
  1183.     }
  1184.     handlerIn = 1;
  1185.  
  1186.     /* function catchers */
  1187.  
  1188.     oldRectFill = SetFunction(GfxBase, (long) lvoRectFill, myRectFill);
  1189.     if (oldRectFill == 0) {
  1190.         writes("!replace RectFill()");
  1191.         return 0;
  1192.     }
  1193.  
  1194.     oldScrollRaster = SetFunction(GfxBase, (long) lvoScrollRaster,
  1195.                                     myScrollRaster);
  1196.     if (oldScrollRaster == 0) {
  1197.         writes("!replace ScrollRaster()");
  1198.         return 0;
  1199.     }
  1200.  
  1201.     oldCloseWindow = SetFunction(IntuitionBase, (long) lvoCloseWindow,
  1202.                                     myCloseWindow);
  1203.     if (oldCloseWindow == 0) {
  1204.         writes("!replace CloseWindow()");
  1205.         return 0;
  1206.     }
  1207.  
  1208.     return 1;
  1209. }
  1210.  
  1211. /*********************************************/
  1212.  
  1213. int jump(mode)
  1214. int mode;
  1215. {
  1216.     char ch;
  1217.  
  1218.     while (0 < msgp->alen--) {
  1219.         ch = *msgp->aptr++;
  1220.         if ((ch != ' ' && ch != '\t' && ch != '\n') == mode)
  1221.             return ch;
  1222.     }
  1223.     return 0;
  1224. }
  1225.  
  1226. /*********************************************/
  1227.  
  1228. int innum(base)
  1229. int base;
  1230. {
  1231.     int result, neg, ch;
  1232.  
  1233.     result = 0;
  1234.     ch = jump(1);
  1235.     if (!ch)
  1236.         return 0;
  1237.  
  1238.     neg = ch == '-';
  1239.     if ((neg || ch == '+') && 0 < msgp->alen--)
  1240.         ch = *msgp->aptr++;
  1241.  
  1242.     while (1) {
  1243.         ch -= '0';
  1244.         if (9 < ch)
  1245.             ch -= 7;    /* was 'A'-'F' */
  1246.         if (15 < ch)
  1247.             ch -= 32;    /* was 'a'-'f' */
  1248.  
  1249.         if (ch < 0 || base <= ch) {
  1250.             msgp->alen++;    /* ungetc */
  1251.             msgp->aptr--;
  1252.             break;
  1253.         }
  1254.  
  1255.         result = result * base + ch;
  1256.  
  1257.         if (msgp->alen-- <= 0)
  1258.             break;
  1259.  
  1260.         ch = *msgp->aptr++;
  1261.     }
  1262.     return neg ? -result : result;
  1263. }
  1264.  
  1265. /*********************************************/
  1266.  
  1267. usage()
  1268. {
  1269. writes("Usage: snipit [opts]");
  1270. writes("where opts can be any of:");
  1271. writes("   ? or h         Help; this text");
  1272. writes("   q              Quit; remove SnipIt from the system");
  1273. writes("   p \"prestring\"  When pasting using Command-B key, insert");
  1274. writes("                  \"prestring\" before each line.  In quotes");
  1275. writes("   l 1 or 0       Lock layer (or don't) while snipping");
  1276. writes("   u +/-number    Adjust cell x position in console windows");
  1277. writes("   v +/-number    Adjust cell y position in console windows");
  1278. writes("   x +/-number    Adjust cell x position in non-console windows");
  1279. writes("   y +/-number    Adjust cell y position in non-console windows");
  1280. writes("   a hex-number   Qualifier for Command-A key (default LEFT-AMIGA)");
  1281. writes("   b hex-number   Qualifier for Command-B key (default LEFT-ALT)");
  1282. writes("");
  1283. writes("Defaults are:  p\"> \" l0 u0 v0 x0 y0 a0040 b0010");
  1284. }
  1285.  
  1286. /*********************************************/
  1287.  
  1288. int options()
  1289. {
  1290.     char *cp;
  1291.     int temp, ch;
  1292.  
  1293.     msgp->done = msgp->huh = msgp->off = 0;
  1294.  
  1295.     do {
  1296.         /* locate a char after whitespace */
  1297.         ch = jump(1);                    /* advance to 1st non-white */
  1298.  
  1299.         if ('A' <= ch && ch <= 'Z')
  1300.             ch = ch - 'A' + 'a';        /* tolower */
  1301.  
  1302.         /* act on char */
  1303.         switch (ch) {
  1304.  
  1305.         case 0:        break;
  1306.  
  1307.         case 'q':    msgp->done = 1;
  1308.                     return 0;            /* die */
  1309.  
  1310.         case 'p':    cp = preString;
  1311.                     ch = jump(1);        /* delim char */
  1312.                     if (ch) {
  1313.                         while (0 < msgp->alen-- &&
  1314.                                (*cp = *msgp->aptr++) != ch) {
  1315.                             cp++;
  1316.                             if (preString + PRE_SIZE <= cp)
  1317.                                 break;
  1318.                         }
  1319.                     }
  1320.                     *cp = 0;
  1321.                     break;
  1322.  
  1323.         case 'x':    if (snip == WIN_SNIP)
  1324.                         clearHi();
  1325.                     msgp->off = 1;
  1326.                     win_offx += innum(10);
  1327.                     break;
  1328.  
  1329.         case 'y':    if (snip == WIN_SNIP)
  1330.                         clearHi();
  1331.                     msgp->off = 1;
  1332.                     win_offy += innum(10);
  1333.                     break;
  1334.  
  1335.         case 'u':    if (snip == CON_SNIP)
  1336.                         clearHi();
  1337.                     msgp->off = 1;
  1338.                     con_offx += innum(10);
  1339.                     break;
  1340.  
  1341.         case 'v':    if (snip == CON_SNIP)
  1342.                         clearHi();
  1343.                     msgp->off = 1;
  1344.                     con_offy += innum(10);
  1345.                     break;
  1346.  
  1347.         case 'a':    if (temp = innum(16));
  1348.                         cmd1 = temp;
  1349.                     break;
  1350.  
  1351.         case 'b':    if (temp = innum(16));
  1352.                         cmd2 = temp;
  1353.                     break;
  1354.  
  1355.         case 'l':    ch = jump(1);        /* first char */
  1356.                     if (ch)
  1357.                         lock_layer = ch == '1';
  1358.                     break;
  1359.  
  1360.         case 'w':    ch = jump(1);        /* first char */
  1361.                     if (ch)
  1362.                         windows = ch == '1';
  1363.                     break;
  1364.  
  1365.         default:    msgp->huh = 1;        /* newline, too - end of string */
  1366.                     break;
  1367.         }
  1368.  
  1369.     } while (jump(0));                    /* advance to whitespace */
  1370.  
  1371.     if (msgp->off) {
  1372.         win_offx = win_offx < -32 ? -32 : 32 < win_offx ? 32 : win_offx;
  1373.         win_offy = win_offy < -32 ? -32 : 32 < win_offy ? 32 : win_offy;
  1374.         con_offx = con_offx < -32 ? -32 : 32 < con_offx ? 32 : con_offx;
  1375.         con_offy = con_offy < -32 ? -32 : 32 < con_offy ? 32 : con_offy;
  1376.  
  1377.         msgp->w_offx = win_offx;
  1378.         msgp->w_offy = win_offy;
  1379.         msgp->c_offx = con_offx;
  1380.         msgp->c_offy = con_offy;
  1381.     }
  1382.  
  1383.     return 1;    /* i.e., keep running */
  1384. }
  1385.  
  1386. /*********************************************/
  1387.  
  1388. outnum(n)
  1389. int n;
  1390. {
  1391.     char d;
  1392.  
  1393.     if (n < 0) {
  1394.         n = -n;
  1395.         _Write(output, "-", 1L);
  1396.     }
  1397.     if (n > 9) {
  1398.         d = n / 10 + '0';
  1399.         _Write(output, &d, 1L);
  1400.     }
  1401.     d = n % 10 + '0';
  1402.     _Write(output, &d, 1L);
  1403. }
  1404.  
  1405. /*********************************************/
  1406.  
  1407. currAdjust(type, x, y)
  1408. char *type;
  1409. int x, y;
  1410. {
  1411.     _Write(output, type, 7L);
  1412.     _Write(output, " adjustment now: x=", 19L);
  1413.     outnum(x);
  1414.     _Write(output, ",y=", 3L);
  1415.     outnum(y);
  1416.     _Write(output, "\n", 1L);
  1417. }
  1418.  
  1419. /*********************************************/
  1420.  
  1421. checkStatus()
  1422. {
  1423.     if (myMsg.huh)
  1424.         writes(huh_msg);
  1425.  
  1426.     else if (myMsg.done)
  1427.         writes("_ cancelled.");
  1428.  
  1429.     else if (myMsg.off) {
  1430.         currAdjust("Console", myMsg.c_offx, myMsg.c_offy);
  1431.         currAdjust("Window ", myMsg.w_offx, myMsg.w_offy);
  1432.     }
  1433. }
  1434.  
  1435. /*********************************************/
  1436.  
  1437. _main(alen, aptr)    /* DOSBase and ExecBase opened already by crt0.o */
  1438. long alen;
  1439. char *aptr;
  1440. {
  1441.     static int pass;
  1442.     int keep_going;
  1443.     long sige, sigt;
  1444.     struct MsgPort *port, *rport;
  1445.  
  1446.     /* sever seglists */
  1447.     do_detach(&alen, &aptr);
  1448.  
  1449.     myMsg.alen = alen;
  1450.     myMsg.aptr = aptr;
  1451.  
  1452.     /* help requested?? */
  1453.     if (*aptr == '?' || *aptr == 'h')
  1454.         usage();
  1455.  
  1456.     /* installed already? if so, pass arguments */
  1457.     else if (port = FindPort(port_name + 1)) {    
  1458.  
  1459.         if (alen <= 1)
  1460.             writes("_ already installed!");
  1461.  
  1462.         else {
  1463.             myMsg.m.mn_ReplyPort = rport = CreatePort(NULL, 0L);
  1464.             if (!rport)
  1465.                 writes("^a port");
  1466.  
  1467.             else {
  1468.                 PutMsg(port, &myMsg);
  1469.                 _WaitPort(rport);        /* wait for reply */
  1470.                 _GetMsg(rport);
  1471.                 DeletePort(rport);
  1472.  
  1473.                 /* check return stats */
  1474.                 checkStatus();
  1475.             }
  1476.         }
  1477.     }
  1478.  
  1479.     /* install & deal with args */
  1480.     else if (init()) {
  1481.  
  1482.         msgp = &myMsg;
  1483.         if (options() && !myMsg.huh) {
  1484.  
  1485.             writes("_ installed.  \xA9 1988 - Scott Evernden");
  1486.  
  1487.             running = 1;
  1488.  
  1489.             /* signals which mean something */
  1490.             sige = 1L << mySignal;            /* request for recognition */
  1491.             sigt = 1L << myPort->mp_SigBit;    /* options message */
  1492.  
  1493.             /* process requests for handler code
  1494.              * while awaiting options signal
  1495.              */
  1496.  
  1497.             keep_going = 1;
  1498.             while (keep_going) {
  1499.  
  1500.                 if (Wait(sige | sigt) == sige) {
  1501.                     buildEvents();
  1502.                     jobFlag = 0;        /* lower active flag */
  1503.                 }
  1504.                 else while (msgp = (struct MyMessage *) GetMsg(myPort)) {
  1505.                     keep_going = options();
  1506.                     _ReplyMsg(msgp);
  1507.                 }
  1508.             }
  1509.         }
  1510.  
  1511.         else { 
  1512.             if (myMsg.huh)
  1513.                 writes(huh_msg);
  1514.  
  1515.             writes("_ not installed.");
  1516.         }
  1517.     }
  1518.  
  1519.     running = 1;
  1520.  
  1521.     /* terminate */
  1522.     Delay(10L);
  1523.     fini();
  1524. }
  1525.  
  1526. SHAR_EOF
  1527. cat << \SHAR_EOF > patch.c
  1528. /* "Patch" fix SnipIt to use a different keymap */
  1529. /* 9/1/88 - Scott Evernden */
  1530.  
  1531. #include <stdio.h>
  1532. #include <ctype.h>
  1533.  
  1534. FILE *infile, *datafile;
  1535.  
  1536. /* original keycode table starts like this... */
  1537. unsigned char match[] = {
  1538.     0x40, 0x81, 0xAA, 0x83, 0x84, 0x85, 0x87, 0x2A,
  1539.     0x89, 0x8A, 0x88, 0x8C, 0x38, 0x0B, 0x39, 0x3A,
  1540.     0x0A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0
  1541. };
  1542.  
  1543. main()
  1544. {
  1545.     long pos, ftell();
  1546.     unsigned char *mp;
  1547.     int ch, i;
  1548.  
  1549.     /* gonna write into this file */
  1550.     infile = fopen("SnipIt", "r+");
  1551.     if (!infile) {
  1552.         puts("Can't open \"SnipIt\"");
  1553.         exit(0);
  1554.     }
  1555.  
  1556.     /8 need to read this one */
  1557.     datafile = fopen("SnipIt.keys", "r");
  1558.     if (!datafile) {
  1559.         puts("Can't open \"SnipIt.keys\"");
  1560.         exit(0);
  1561.     }
  1562.  
  1563.     /* locate original table */
  1564.     mp = match;
  1565.     while (*mp && (ch = fgetc(infile)) != EOF) {
  1566.         if (ch != *mp)
  1567.             mp = match;
  1568.         else if (mp++ == match)
  1569.             pos = ftell(infile) - 1;
  1570.     }
  1571.  
  1572.     if (ch == EOF) {
  1573.         puts("Are you sure this is an original copy of \"SnipIt\"?");
  1574.         fclose(infile);
  1575.         fclose(datafile);
  1576.         exit(0);
  1577.     }
  1578.  
  1579.     fputs("Patching keytable...", stdout);
  1580.  
  1581.     fseek(infile, pos, 0L);
  1582.  
  1583.     for (i = 32; i < 127; i++)
  1584.         fputc(innum() & 0xFF, infile);
  1585.  
  1586.     fclose(infile);
  1587.     fclose(datafile);
  1588.     puts("done");
  1589. }
  1590.  
  1591.  
  1592. innum()
  1593. {
  1594.     int result;
  1595.     int ch;
  1596.  
  1597.     do {
  1598.         ch = fgetc(datafile);
  1599.     } while (!isxdigit(ch));
  1600.  
  1601.     if (ch == EOF)
  1602.         return 0;
  1603.  
  1604.     result = 0;
  1605.     do {
  1606.         ch -= '0';
  1607.         if (9 < ch)
  1608.             ch -= 7;
  1609.         if (15 < ch)
  1610.             ch -= 32;
  1611.         result = result * 16 + ch;
  1612.         ch = fgetc(datafile);
  1613.     } while (isxdigit(ch));
  1614.  
  1615.     return result;
  1616. }
  1617.  
  1618.  
  1619. SHAR_EOF
  1620. cat << \SHAR_EOF > reco.c
  1621. /* :ts=4
  1622.  *
  1623.  * Amiga SnipIt 1.2
  1624.  * (c) (opyright 1987,1988 - Scott Evernden - All Rights Reserved
  1625.  *
  1626.  * reco.c - recognize & construct char code input
  1627.  *
  1628.  */
  1629.  
  1630. #include "hs.h"
  1631.  
  1632. char *_AllocMem();
  1633.  
  1634. /* ascii to keycode (this is a hack; is there a correct way to do this?) */
  1635. char table[] = {
  1636. /*             !     "     #     $     %     &     '  */
  1637. /*       (     )     *     +     ,     -     .     /  */
  1638. /*     0     1     2     3     4     5     6     7  */
  1639. /*     8     9     :     ;     <     =     >     ?  */
  1640. /*     @     A     B     C     D     E     F     G  */
  1641. /*     H     I     J     K     L     M     N     O  */
  1642. /*     P     Q     R     S     T     U     V     W  */
  1643. /*     X     Y     Z     [     \     ]     ^     _  */
  1644. /*     `     a     b     c     d     e     f     g  */
  1645. /*     h     i     j     k     l     m     n     o  */
  1646. /*     p     q     r     s     t     u     v     w  */
  1647. /*     x     y     z     {     |     }     ~        */
  1648.     0x40, 0x81, 0xAA, 0x83, 0x84, 0x85, 0x87, 0x2A,
  1649.     0x89, 0x8A, 0x88, 0x8C, 0x38, 0x0B, 0x39, 0x3A,
  1650.     0x0A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
  1651.     0x08, 0x09, 0xA9, 0x29, 0xB8, 0x0C, 0xB9, 0xBA,
  1652.     0x82, 0xA0, 0xB5, 0xB3, 0xA2, 0x92, 0xA3, 0xA4,
  1653.     0xA5, 0x97, 0xA6, 0xA7, 0xA8, 0xB7, 0xB6, 0x98,
  1654.     0x99, 0x90, 0x93, 0xA1, 0x94, 0x96, 0xB4, 0x91,
  1655.     0xB2, 0x95, 0xB1, 0x1A, 0x0D, 0x1B, 0x86, 0x8B,
  1656.     0x00, 0x20, 0x35, 0x33, 0x22, 0x12, 0x23, 0x24,
  1657.     0x25, 0x17, 0x26, 0x27, 0x28, 0x37, 0x36, 0x18,
  1658.     0x19, 0x10, 0x13, 0x21, 0x14, 0x16, 0x34, 0x11,
  1659.     0x32, 0x15, 0x31, 0x9A, 0x8D, 0x9B, 0x80
  1660. };
  1661.  
  1662. static struct InputEvent event;
  1663. char *evs, *evp;
  1664. char preString[PRE_SIZE + 1] = "> ";    /* a prestring */
  1665. int evslen;
  1666.  
  1667. extern struct IOStdReq *inpReq;
  1668. extern struct TextFont *capttf;
  1669. extern struct BitMap captbm;
  1670. extern int captx, capty;
  1671. extern int charx, chary;
  1672. extern int left, right;
  1673. extern int cmd1, cmd2, jobFlag;
  1674.  
  1675. /*********************************************/
  1676.  
  1677. /* cleanup, local to this module */
  1678. finiReco()
  1679. {
  1680.     /* event string is allocated */
  1681.     if (evs)
  1682.         _FreeMem(evs, (long) evslen);
  1683. }
  1684.  
  1685. /*********************************************/
  1686.  
  1687. /* entry to recognizer; generates keycode events from the capture bitmap */
  1688. buildEvents()
  1689. {
  1690.     register char *cp;
  1691.     PLANEPTR p;
  1692.     int code;
  1693.  
  1694.     /* prepare request to input device */
  1695.     inpReq->io_Command = IND_WRITEEVENT;
  1696.     inpReq->io_Flags = 0;
  1697.     inpReq->io_Length = sizeof (struct InputEvent);
  1698.     inpReq->io_Data = (APTR) &event;
  1699.  
  1700.     /* new snip-map? */
  1701.     if (capttf) {
  1702.  
  1703.         /* new buffer for keycodes */
  1704.         if (evs)
  1705.             _FreeMem(evs, (long) evslen);
  1706.  
  1707.         evslen = (captx / charx) * (capty / chary);
  1708.         evs = (char *) _AllocMem((long) evslen, 0L);
  1709.  
  1710.         if (evp = evs)
  1711.             buildCodes();
  1712.  
  1713.         capttf = NULL;        /* reset "newly-captured" indicator */
  1714.  
  1715.         /* reco'ed, so drop the bitmap */
  1716.         if (p = captbm.Planes[0]) {
  1717.             FreeRaster(p, (long) captx, (long) capty);
  1718.             captbm.Planes[0] = NULL;
  1719.         }
  1720.     }
  1721.     else if (evp = evs) {
  1722.  
  1723.         while (*evp != -1) {
  1724.  
  1725.             if (jobFlag & cmd2) {
  1726.                 cp = preString;
  1727.                 while (*cp)
  1728.                     sendKey(*cp++);
  1729.             }
  1730.  
  1731.             do
  1732.                 sendKey(code = *evp++);
  1733.             while (code != '\n' && *evp != -1);
  1734.         }
  1735.     }
  1736. }
  1737.  
  1738. /*********************************************/
  1739.  
  1740. /* inject a (fake) keyboard press/release into the input stream */
  1741. sendKey(code)
  1742. int code;
  1743. {
  1744.     /* convert to raw key */
  1745.     code = code == '\n' ? 0x44 : table[code - 32];
  1746.  
  1747.     /* build key down event */
  1748.     event.ie_Class = IECLASS_RAWKEY;
  1749.     event.ie_Code = code & 0x7F;
  1750.     event.ie_Qualifier = IEQUALIFIER_RELATIVEMOUSE;
  1751.     if (code & 0x80)
  1752.         event.ie_Qualifier |= IEQUALIFIER_LSHIFT;
  1753.     event.ie_NextEvent = NULL;
  1754.  
  1755.     /* make it happen */
  1756.     DoIO(inpReq);
  1757.  
  1758.     /* build key up event (req'd?) */
  1759.     event.ie_Class = IECLASS_RAWKEY;
  1760.     event.ie_Code = (code & 0x7F) | IECODE_UP_PREFIX;
  1761.     event.ie_Qualifier = IEQUALIFIER_RELATIVEMOUSE;
  1762.     if (code & 0x80)
  1763.         event.ie_Qualifier |= IEQUALIFIER_LSHIFT;
  1764.     event.ie_NextEvent = NULL;
  1765.  
  1766.     /* make it happen */
  1767.     DoIO(inpReq);
  1768. }
  1769.  
  1770. /*********************************************/
  1771.  
  1772. /* actually makes the keycodes */
  1773. buildCodes()
  1774. {
  1775.     register int code, px, py, wid, lastx, lasty, spaces;
  1776.     char *cp;
  1777.  
  1778.     /* heuristics for text structure (i.e., newlines) */
  1779.     px = left;
  1780.     py = 0;
  1781.     lastx = captx / charx - 1;
  1782.     lasty = capty / chary - 1;
  1783.     wid = lastx;
  1784.  
  1785.     while (py <= lasty) {
  1786.  
  1787.         /* prestring on cmd2 key */
  1788.         if (jobFlag & cmd2) {
  1789.             cp = preString;
  1790.             while (*cp)
  1791.                 sendKey(*cp++);        /* don't record */
  1792.         }
  1793.  
  1794.         /* on the last line? */
  1795.         if (py == lasty)
  1796.             lastx = right;
  1797.  
  1798.         /* for each cell... */
  1799.         while (px <= lastx) {
  1800.  
  1801.             /* recognize single character */
  1802.             code = reco(px++, py);
  1803.  
  1804.             /* we're gonna count runs of spaces */
  1805.             spaces = 0;
  1806.             while (code == ' ' && px <= wid) {
  1807.                 spaces++;
  1808.                 code = reco(px++, py);
  1809.             }
  1810.  
  1811.             /* send / record, if no spaces */
  1812.             if (!spaces)
  1813.                 sendKey(*evp++ = code);
  1814.  
  1815.             /* if end of line is all spaces, then regard as newline */
  1816.             else if (code == ' ' && wid < px)
  1817.                 sendKey(*evp++ = '\n');
  1818.  
  1819.             /* if more text on line after snip area, then not a newline */
  1820.             else if (py < lasty || px <= lastx + 1) {
  1821.                 while (spaces--)
  1822.                     sendKey(*evp++ = ' ');
  1823.                 sendKey(*evp++ = code);
  1824.             }
  1825.  
  1826.             /* emit spaces */
  1827.             else {
  1828.                 spaces -= px - lastx - 2;
  1829.                 while (spaces--)
  1830.                     sendKey(*evp++ = ' ');
  1831.             }
  1832.         }
  1833.  
  1834.         /* next is leftside of next row down */
  1835.         px = 0;
  1836.         py++;
  1837.     }
  1838.  
  1839.     *evp = -1;        /* record terminator */
  1840. }
  1841.  
  1842. /*********************************************/
  1843.  
  1844. /* return ascii code of character in capture bitmap at (x,y) */
  1845. int reco(x, y)
  1846. int x, y;
  1847. {
  1848.     register char *s, *d, *sp, *dp;
  1849.     register int hyt, i;
  1850.  
  1851.     /* recognize cell at (x,y) */
  1852.     sp = (char *) capttf->tf_CharData;
  1853.     dp = (char *) captbm.Planes[0] + y * chary * captbm.BytesPerRow + x;
  1854.  
  1855.     for (i = 32; i < 128; sp++, i++) {
  1856.         s = sp;
  1857.         d = dp;
  1858.         hyt = capttf->tf_YSize;
  1859.  
  1860.         if (*s == *d) {
  1861.             do {
  1862.                 if (--hyt == 0)
  1863.                     return i;
  1864.                 s += capttf->tf_Modulo;
  1865.                 d += captbm.BytesPerRow;
  1866.             } while (*s == *d);
  1867.         }
  1868.         else if (*s == ~*d) {
  1869.             do {
  1870.                 if (--hyt == 0)
  1871.                     return i;
  1872.                 s += capttf->tf_Modulo;
  1873.                 d += captbm.BytesPerRow;
  1874.             } while (*s == ~*d);
  1875.         }
  1876.     }
  1877.  
  1878.     return '?';    /* unknown */
  1879. }
  1880.  
  1881. SHAR_EOF
  1882. cat << \SHAR_EOF > snipit.keys
  1883. 40 81 AA 83 84 85 87 2A
  1884. 89 8A 88 8C 38 0B 39 3A
  1885. 0A 01 02 03 04 05 06 07
  1886. 08 09 A9 29 B8 0C B9 BA
  1887. 82 A0 B5 B3 A2 92 A3 A4
  1888. A5 97 A6 A7 A8 B7 B6 98
  1889. 99 90 93 A1 94 96 B4 91
  1890. B2 95 B1 1A 0D 1B 86 8B
  1891. 00 20 35 33 22 12 23 24
  1892. 25 17 26 27 28 37 36 18
  1893. 19 10 13 21 14 16 34 11
  1894. 32 15 31 9A 8D 9B 80
  1895.  
  1896. SHAR_EOF
  1897. cat << \SHAR_EOF > patch.doc
  1898. KeyMap patcher:
  1899. ==============
  1900.  
  1901. The program "patch" will "fix" SnipIt to work with foreign, custom, and the
  1902. Dvorak keymaps.  This measure is a stopgap "bandaid" (i.e., hack) until a
  1903. more appropriate handling of KeyMaps is employed by SnipIt.
  1904.  
  1905. Make sure that (a copy of) "snipit" and a file named "snipit.keys" are in
  1906. the 'current directory'.  Simply incant:
  1907.  
  1908.     > patch
  1909.  
  1910. and SnipIt will be modified according to the data in the "snipit.keys" file.
  1911.  
  1912. The file "snipit.keys" has a format like the following (this example is
  1913. the default- for the 'usa0' keymap):
  1914.  
  1915. 40 81 AA 83 84 85 87 2A
  1916. 89 8A 88 8C 38 0B 39 3A
  1917. 0A 01 02 03 04 05 06 07
  1918. 08 09 A9 29 B8 0C B9 BA
  1919. 82 A0 B5 B3 A2 92 A3 A4
  1920. A5 97 A6 A7 A8 B7 B6 98
  1921. 99 90 93 A1 94 96 B4 91
  1922. B2 95 B1 1A 0D 1B 86 8B
  1923. 00 20 35 33 22 12 23 24
  1924. 25 17 26 27 28 37 36 18
  1925. 19 10 13 21 14 16 34 11
  1926. 32 15 31 9A 8D 9B 80
  1927.  
  1928. It should be a list of 95 hexadecimal numbers, each corresponding to the
  1929. ASCII codes 32-126 (95 codes- ' ' thru '~').  The hex number is the I.D.
  1930. of the keyboard key (as revealed in the Appendix to the AmigaDOS Technical
  1931. Manual and other sources).  If the keyboard key must be "shifted" in order
  1932. to achieve the corresponding ASCII code, then the hex keycode number is
  1933. "OR"ed with an 0x80 (high bit on).
  1934.  
  1935. The patch program simply searches the SnipIt program file looking for the
  1936. original hardwired table, and then overwrites the 95 code values.
  1937. Consequently, you need to run "patch" on the original copy of SnipIt.
  1938.  
  1939. -scott
  1940.  
  1941. SHAR_EOF
  1942. cat << \SHAR_EOF > snipit.doc
  1943. SnipIt 1.2  -  Copyright (c) 1988 - Scott Evernden,  All Rights Reserved
  1944.  
  1945.  
  1946. What is SnipIt?
  1947. ================
  1948.  
  1949. SnipIt is a CLI program which allows you to copy text directly from  the
  1950. Amiga  screen  in any window, and then paste it into any other place, as
  1951. though you had typed that text at the keyboard.  You mark the  text  you
  1952. want  to  'snip' using the mouse.  You also use the mouse to 'paste' the
  1953. last snipped text into the active window, requester, or anywhere.
  1954.  
  1955. SnipIt is a program which installs itself into the input stream handling
  1956. code  of  AmigaDOS.   It  waits  for you to hold down the LEFT-AMIGA (or
  1957. optionally another key) while using the mouse.
  1958.  
  1959.  
  1960. Running the Program
  1961. ===================
  1962.  
  1963. This program will only run properly from the CLI.  You start it like
  1964.  
  1965.   > snipit
  1966.  
  1967. at which point, SnipIt will install itself, and print a message.
  1968.  
  1969. You can control certain operations and modes of SnipIt  when  you  first
  1970. install  it  and  later  while  it  is  running.   You do this by typing
  1971. "snipit" with 'option' letters and possible arguments.  For example, you
  1972. can tell SnipIt to stop running:
  1973.  
  1974.   > snipit q
  1975.  
  1976. In  other  words,  type  "snipit"  followed  by a "q" for 'quit'.  Other
  1977. options to control SnipIt's behavior will be described below.
  1978.  
  1979.  
  1980. Marking Text to be Copied
  1981. =========================
  1982.  
  1983. To mark text to  be  copied,  simply  depress  the  LEFT-AMIGA  key  (by
  1984. default),  move the mouse pointer to a position in any window containing
  1985. text and hold down the LEFT mouse button.  While holding down  the  LEFT
  1986. mouse button you move the mouse to the opposite end of the text area you
  1987. want to copy and then  release.   As  you  do  this,  SnipIt  will  mark
  1988. (hilight) both ends of the area you are designating.
  1989.  
  1990. Once  you  have  released  the  LEFT  mouse  button,  SnipIt  will fully
  1991. highlight and 'snapshot' the text within the area you have marked out.
  1992.  
  1993.  
  1994. Pasting the Copied Text
  1995. =======================
  1996.  
  1997. You can deposit  the  text  you  copied  by,  again,  holding  down  the
  1998. LEFT-AMIGA key, and clicking the RIGHT mouse button.
  1999.  
  2000. SnipIt  will  inject  keystroke  codes into the input stream, so you can
  2001. paste text into any active window, requester, or anything else which  is
  2002. expecting keyboard input.
  2003.  
  2004. You can paste copied text as many times as you want.
  2005.  
  2006. SnipIt  will  un-hilight the selected area whenever any output occurs in
  2007. the highlighted window.  You can still paste the copied  text,  however,
  2008. even though the highlighting has been removed.
  2009.  
  2010.  
  2011. Limitations of This Version
  2012. ===========================
  2013.  
  2014. SnipIt  can  recognize any font in any height, only as long as that font
  2015. is fixed width and 8 pixels wide.
  2016.  
  2017. SnipIt in its current form cannot recognize text  which  is  italicised,
  2018. underlined, or is drawn in certain colors.  In some unusual colored text
  2019. cases, SnipIt will be 'blind' thinking it is  seeing  space  characters,
  2020. and you will get nothing but spaces while pasting.
  2021.  
  2022. SnipIt  can  only  recognize  character  codes  between ASCII 32-127, so
  2023. special characters (requiring the ALT key  to  generate)  will  not  get
  2024. recognized  properly.   If SnipIt cannot figure out a character, it will
  2025. substitute a '?' (question mark) character.
  2026.  
  2027. SnipIt appears to work properly  with  the  ConMan  replacement  console
  2028. handler by William Hawes.  SnipIt also appears to work properly with the
  2029. NEWCON:  window of AmigaDOS  1.3.   SnipIt  may  highlight  areas  in  a
  2030. peculiar  fashion  in  windows  having the GIMMEZEROZERO attribute (eg.,
  2031. AmigaBasic).
  2032.  
  2033. This program will also co-operate with programs like SunMouse and others
  2034. which can change window activation automatically.   However,  note  that
  2035. each  character  of  any  pasted text will arrive in whatever window the
  2036. mouse is currently in.
  2037.  
  2038.  
  2039. New Features of Version 1.2
  2040. ===========================
  2041.  
  2042. Automatically runs in the background
  2043. ------------------------------------
  2044. You no longer need to 'run'  SnipIt-  the  program  is  now  capable  of
  2045. detaching itself and running automatically in the background.
  2046.  
  2047. Snips from both consoles and regular windows
  2048. --------------------------------------------
  2049. SnipIt  can  now  recognize  text  in  plain  old windows (not only just
  2050. console windows anymore).  So, applications like  WPLibrary  P-Edit  and
  2051. VT100 terminal programs can be 'snipped' from.  Note that SnipIt assumes
  2052. that text is being displayed in the window is some kind  of  cell  array
  2053. (like  a terminal).  It probably won't do what you want in programs like
  2054. Deluxe Paint, and others which can place text anywhere in the window.
  2055.  
  2056. Built in mini-help
  2057. ------------------
  2058. SnipIt will give you a quick rundown of its options if you type:
  2059.  
  2060.   > snipit h
  2061.  
  2062. or
  2063.  
  2064.   > snipit ?
  2065.  
  2066. Prestring insertion while pasting
  2067. ---------------------------------
  2068. The program now provides an option to insert a  short  text  string 
  2069. before each line of characters as it is pasted.  This can be useful
  2070. if  you are 'snipping' text which you wish to 'quote'.  You do this
  2071. by depressing  the   LEFT-ALT  key  (by  default),  instead  of the
  2072. LEFT-AMIGA key while pasting.  For  example,  if  I  snip, and then
  2073. paste this paragraph using LEFT-ALT, I get:
  2074.  
  2075. > The program now provides an option to insert a  short  text  string
  2076. > before each line of characters as it is pasted.  This can be useful
  2077. > if  you are 'snipping' text which you wish to 'quote'.  You do this
  2078. > by depressing  the   LEFT-ALT  key  (by  default),  instead  of the
  2079. > LEFT-AMIGA key while pasting.  For  example,  if  I  snip, and then
  2080. > paste this paragraph using LEFT-ALT, I get:
  2081.  
  2082. Note,  a  ">  "  (the  default) string has been prepended to each pasted
  2083. line.  This string can be changed at any time by:
  2084.  
  2085.   > snipit p "the prestring:  "
  2086.  
  2087. where the text appears between quotes after a "p".   Actually,  you  can
  2088. use any delimiter, and not only quotes, like:
  2089.  
  2090.   > snipit p .the prestring:  .
  2091.  
  2092. Just  repeat  the  initial  character  at  the end.  Your prestring must
  2093. contain no more than 32 characters.
  2094.  
  2095. Character cell location adjustments
  2096. -----------------------------------
  2097. Sometimes, in non-console  windows,  the  text  may  not  be  placed  in
  2098. positions  that SnipIt can locate.  SnipIt 1.2 now provides options that
  2099. allow you to slightly adjust its idea of where characters are located in
  2100. the window:
  2101.  
  2102.   > snipit x +2 y -1
  2103.  
  2104. will move the snip area in windows, right by 2 pixels and up by one.  If
  2105. you find that SnipIt is producing lots of ???????s while  pasting,  then
  2106. you  may  need  to  use this option to adjust the cell area (highlighted
  2107. area) slightly.  For example, P-Edit currently requires:
  2108.  
  2109.   > snipit x -1
  2110.  
  2111. as text characters are draw one pixel higher than SnipIt would otherwise
  2112. assume.  Dave Wecker's VT100 currently requires:
  2113.  
  2114.   > snipit y -1
  2115.  
  2116.  
  2117. You can also correct the x and y cell positions in console windows using
  2118. the 'u' and 'v' options:
  2119.  
  2120.   > snipit u -3 v +1
  2121.  
  2122. will move the snip area in consoles, left by 3 pixels, and down by  one.
  2123. For  example,  Eric  Haberfellner's Handshake (VT100 emulator) currently
  2124. needs:
  2125.  
  2126.   > snipit v +3
  2127.  
  2128. In most circumstances, you shouldn't need to use the 'u' and 'v' options
  2129. to adjust for console windows.
  2130.  
  2131.  
  2132. Improved recognition
  2133. --------------------
  2134. SnipIt  can  now  recognize  highlighted and inverted characters- you no
  2135. longer have to move that darn cursor away from your text.
  2136.  
  2137. Freeze windows while snipping
  2138. -----------------------------
  2139. If you type:
  2140.  
  2141.   > snipit l 1
  2142.  
  2143. ("l" for 'lock') Snipit 1.2 will freeze the window or console which  you
  2144. are  snipping from.  This can be useful if you are trying to 'snip' text
  2145. in a window that would otherwise scroll.
  2146.  
  2147.   > snipit l 0
  2148.  
  2149. turns this option off.
  2150.  
  2151. Re-assignable keyboard use
  2152. --------------------------
  2153. Normally, you snip and paste using the LEFT-AMIGA  key;  you  can  paste
  2154. with  a  prestring  using  the  LEFT-ALT  key  while pasting.  These key
  2155. choices can be changed.  You change the normal, or Command-A,  key  from
  2156. the LEFT-AMIGA to another key by:
  2157.  
  2158.   > snipit a <hexcode>
  2159.  
  2160. where the <hexcode> is from this table:
  2161.  
  2162.         LEFT-SHIFT ....  0001
  2163.         RIGHT-SHIFT ...  0002
  2164.         CONTROL .......  0008
  2165.         LEFT-ALT ......  0010 <- default Command-B key
  2166.         RIGHT-ALT .....  0020
  2167.         LEFT-AMIGA ....  0040 <- default Command-A key
  2168.         RIGHT-AMIGA ...  0080
  2169.  
  2170. other values won't work.  So, to use the CONTROL key instead, you:
  2171.  
  2172.   > snipit a 0008 (or just 8, you don't need the leading 0s).
  2173.  
  2174. The  Command-B  key,  normally  the  LEFT-ALT  key,  can be changed, for
  2175. example, to the Right-Shift key:
  2176.  
  2177.   > snipit b 0002
  2178.  
  2179.  
  2180. Default settings
  2181. ----------------
  2182. By default snipit acts as though you had done:
  2183.  
  2184.   > snipit p"> " l0 u0 v0 x0 y0 a0040 b0010
  2185.  
  2186. meaning:
  2187.  
  2188.   o (p) use "> " as the prestring when pasting with the Command-B key
  2189.   o (l) don't freeze the window being snipped from
  2190.   o (u, v) no adjustment to cell area when snipping from consoles
  2191.   o (x, y) no adjustment to cell area when snipping from windows
  2192.   o (a) use LEFT-AMIGA for Command-A operation-  regular snips and pastes
  2193.   o (b) use LEFT-ALT for Command-B operation- insert prestring on pastes
  2194.  
  2195.  
  2196. Bugs
  2197. ====
  2198.  
  2199. I have not gone to any special effort to check if Windows or Screens are
  2200. closed,  or  otherwise  disappear,  while  the  mouse  is  being used to
  2201. highlight a text area.  The system will likely Guru if this happens.
  2202.  
  2203. SnipIt  only  works  properly with the usa0 keymap (more below).  Dvorak
  2204. (usa2) will not, and certain  non-usa  keyboards/keymaps  may  not  work
  2205. properly with SnipIt.   However, a 'patch' program is included to modify
  2206. SnipIt to work with other keymaps.   See the file "PATCH.DOC"  for  more
  2207. information.
  2208.  
  2209.  
  2210. Ideas for the Future
  2211. ====================
  2212.  
  2213. In approximate order of importance to me:
  2214.  
  2215. The next SnipIt will hopefully do a better job in dealing with  KeyMaps.
  2216. Currently,  SnipIt  uses  a  hardcoded  table  of  keycodes  for pasting
  2217. character codes into the input stream.  I'm not real  happy  with  this,
  2218. because  it  is  not the best design.  This will be fixed next.
  2219.  
  2220. Recognize, as an option, ALL characters, even ones requiring the ALT key
  2221. to generate (full 8-bit ASCII).
  2222.  
  2223. An 'appending' snip.  The next version of SnipIt will probably allow you
  2224. to 'append' or add newly snipped  material  to  the  end  of  previously
  2225. snipped  text.   This  way,  you  could  actually 'compose' a message by
  2226. collecting text from different parts of one  or  several  windows.   The
  2227. Command-B key is planned for this use while snipping.
  2228.  
  2229. Send  snipped text to a device or file instead of into the input stream.
  2230. This way, you could direct snipped text into a PIPE:, for example.
  2231.  
  2232. Use the clipboard- some day.
  2233.  
  2234. Recognize text that isn't 8  pixels  wide,  is  colored,  underlined  or
  2235. italicised.  Don't hold your breath on these.
  2236.  
  2237. The SnipIt program acts like 2 different programs:
  2238.   1. As the resident SnipIt program doing the real work.
  2239.   2. As the user interface communicating options to the resident SnipIt.
  2240.  
  2241. Currently, the resident SnipIt also carries the code used  by  the  user
  2242. interface  portion.   This  is a mild waste of memory (less than 5K).  A
  2243. future version of SnipIt may release code sections not required for  the
  2244. resident portion, thereby reducing consumption of memory.
  2245.  
  2246.  
  2247. ==========================================================================
  2248.  
  2249. Comments and contributions to:
  2250. ------------------------------
  2251.  
  2252. plink:  SCOTT E
  2253. bix:    s_evernden
  2254. cis:    73116,3451
  2255. uucp:   {ames,rutgers}!harvard!m2c!applix!scott
  2256.         scott@applix.m2c.org
  2257.  
  2258. Scott Evernden
  2259. 9 Courtland St.
  2260. Holliston, MA 01746
  2261.  
  2262. SHAR_EOF
  2263. #    End of shell archive
  2264. exit 0
  2265. -- 
  2266. Bob Page, U of Lowell CS Dept.  page@swan.ulowell.edu  ulowell!page
  2267. Have five nice days.
  2268.